package com.magnificent.atlantis.client.ui.planner.panels.task.treetable.data;

import com.magnificent.atlantis.client.data.task.planner.AbstractPlannerTask;
import com.magnificent.atlantis.client.ui.creator.tasktreetable.data.CreatorTableNode;

import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * User: Babanin
 * Date: 24.12.2008
 * Time: 1:50:50
 * <p/>
 * Feci quod potui, faciant meliora potentes.
 */
public class PlannerTableNode {
    private PlannerTableNode parent;
    private AbstractPlannerTask abstractPlannerTask;
    private List<PlannerTableNode> children;

    public PlannerTableNode() {
        abstractPlannerTask = null;
        children = new ArrayList<PlannerTableNode>();
    }

    public PlannerTableNode(AbstractPlannerTask abstractPlannerTask, PlannerTableNode parent) {
        this.parent = parent;
        this.abstractPlannerTask = abstractPlannerTask;
        children = new ArrayList<PlannerTableNode>();
    }

    public List<PlannerTableNode> getChildren() {
        return children;
    }

    public int getChildCount() {
        return children.size();
    }

    public PlannerTableNode getParent() {
        return parent;
    }

    public void setParent(PlannerTableNode parent) {
        this.parent = parent;
    }

    public AbstractPlannerTask getTask() {
        return abstractPlannerTask;
    }

    public void setChildren(List<PlannerTableNode> children) {
        this.children = children;
    }

    public boolean isMain() {
        return (parent != null) && parent.isRoot();
    }

    public boolean isRoot() {
        return (abstractPlannerTask == null) && (parent == null);
    }

    public int getProgress() {
        if (abstractPlannerTask != null) {
            if (abstractPlannerTask.isBasicTask()) {
                return abstractPlannerTask.getBasicTask().getProgress();
            } else {
                return abstractPlannerTask.getMeetingTask().isCompleted() ? 100 : 0;
            }
        }

        return -1;
    }

    public void setProgress(int progress) {
        if (abstractPlannerTask != null) {
            if (abstractPlannerTask.isBasicTask()) {
                abstractPlannerTask.getBasicTask().setProgress(progress);
            } else {
                abstractPlannerTask.getMeetingTask().setCompleted(progress == 100);
            }

            if (getParent() != null) {
                getParent().setProgress(recountProgress());
            }
        }
    }

    private int recountProgress() {
        int brotherCount = getParent().getChildren().size();
        double progressPerChild = 100.0 / brotherCount;

        double progressCount = 0;
        for (PlannerTableNode treeTableNode : getParent().getChildren()) {
            progressCount += ((progressPerChild / 100.0) * treeTableNode.getProgress());
        }

        if (progressCount > 99) {
            if (allChildrenIsFinished(getParent().getChildren())) {
                return 100;
            } else {
                return 99;
            }
        }

        return (int) progressCount;
    }

    public static boolean allChildrenIsFinished(List<PlannerTableNode> children) {
        for (PlannerTableNode treeTableNode : children) {
            if (treeTableNode.getProgress() != 100) {
                return false;
            }
        }

        return true;
    }

    public TreePath getTreePath() {
        PlannerTableNode node = this;
        List<Object> treePath = new ArrayList<Object>();
        while (node != null) {
            treePath.add(node);
            node = node.getParent();
        }

        if (treePath.size() == 0) {
            return new TreePath(this);
        } else {
            Collections.reverse(treePath);
            return new TreePath(treePath.toArray());
        }
    }

    public static Object[] getParentPath(CreatorTableNode node) {
        List<Object> treePath = new ArrayList<Object>();
        while (node.getParent() != null) {
            treePath.add(node.getParent());
            node = node.getParent();
        }

        if (treePath.size() == 0) {
            treePath.add(node);
        } else {
            Collections.reverse(treePath);
        }

        return treePath.toArray();
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PlannerTableNode)) return false;

        PlannerTableNode that = (PlannerTableNode) o;

        return abstractPlannerTask != that.abstractPlannerTask;
    }

    public int hashCode() {
        int result;
        result = (parent != null ? parent.hashCode() : 0);
        result = 31 * result + (abstractPlannerTask != null ? abstractPlannerTask.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return super.toString() + " = " + (abstractPlannerTask != null ? abstractPlannerTask.getName() : "ROOT");
    }
}
